package com.jzo2o.redis.serialize;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.util.Objects;

/**
 * 自定义Redis泛型对象JSON序列化器
 * 功能：继承Spring默认的GenericJackson2JsonRedisSerializer，针对字符串/字符类型做特殊处理，
 * 避免此类对象被序列化为带双引号的JSON格式，减少存储冗余并简化字符串类型的读写逻辑。
 * 适用场景：Redis中需要存储混合类型数据（如字符串、POJO对象等），且希望字符串类型以原生形式存储时使用。
 */
public class ObjectGenericJackson2JsonRedisSerializer extends GenericJackson2JsonRedisSerializer {
    /**
     * 默认实例：使用标准ObjectMapper的序列化器实例，方便直接复用
     */
    public static final ObjectGenericJackson2JsonRedisSerializer DEFAULT_INSTANCE = new ObjectGenericJackson2JsonRedisSerializer(new ObjectMapper());

    public ObjectGenericJackson2JsonRedisSerializer(ObjectMapper mapper){
        super(mapper);
    }


    /**
     * 序列化方法：对字符串/字符类型做特殊处理
     * 逻辑说明：
     * 1. 若待序列化对象为String或Character类型，直接转为字节数组（原生字符串形式）
     * 2. 其他类型（如POJO、集合等）沿用父类的JSON序列化逻辑（带类型信息，支持反序列化）
     *
     * @param source 待序列化的对象
     * @return 序列化后的字节数组
     * @throws SerializationException 序列化失败时抛出
     */
    @Override
    public byte[] serialize(Object source) throws SerializationException {
        if (Objects.nonNull(source)) {
            if (source instanceof String || source instanceof Character) {
                return source.toString().getBytes();
            }
        }
        return super.serialize(source);
    }

    /**
     * 反序列化方法：沿用父类逻辑
     * 说明：父类会根据序列化时保存的类型信息，将JSON字节数组转换为指定类型的对象；
     * 对于字符串类型，由于序列化时未添加JSON引号，反序列化时会直接转为字符串对象。
     *
     * @param source 待反序列化的字节数组
     * @param type 目标对象类型
     * @param <T> 目标类型泛型
     * @return 反序列化后的对象
     * @throws SerializationException 反序列化失败时抛出
     */
    @Override
    public <T> T deserialize(byte[] source, Class<T> type) throws SerializationException {
        return super.deserialize(source, type);
    }

}
